package org.egomsl.mw.record;

import org.egomsl.mw.BytesUtils;

import java.nio.ByteBuffer;
import java.util.Arrays;

public interface Record {
    public static enum Tag {
        INSERT,
        UPDATE,
        DELETE;

        static Tag getTag(int ordinal) {
            for(Tag tag : Tag.values()) {
                if(ordinal == tag.ordinal()) {
                    return tag;
                }
            }
            return null;
        }
    }

    public static class Key {
        /**
         * 主键
         */
        private byte[] keyBytes;
        private int keyOffset;
        private int keyLen;

        /**
         *
         * 当前记录的标签
         */
        private Tag tag;

        /**
         * 当前记录的时间戳，可以根据需要选择是插入时的时间戳或者自己设置的时间戳
         */
        private long timestamp;

        public Key() {
            this(null, null, 0, 0, 0);
        }

        public Key(byte[] key) {
            this(key, null, 0, 0, key.length);
        }

        public Key(byte[] key, Tag tag, long timestamp) {
            this(key, tag, timestamp, 0, key.length);
        }

        public Key(byte[] key, Tag tag, long timestamp, int keyOffset, int keyLen) {
            this.keyBytes = key;
            this.tag = tag;
            this.timestamp = timestamp;
            this.keyOffset = keyOffset;
            this.keyLen = keyLen;
        }

        public byte[] getKeyBytes() {
            return keyBytes;
        }

        public void setKeyBytes(byte[] keyBytes) {
            this.keyBytes = keyBytes;
        }

        public void setKeyBytes(byte[] keyBytes, int keyOffset, int keyLen) {
            this.keyBytes = keyBytes;
            this.keyOffset = keyOffset;
            this.keyLen = keyLen;
        }

        public Tag getTag() {
            return tag;
        }

        public void setTag(Tag tag) {
            this.tag = tag;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(long timestamp) {
            this.timestamp = timestamp;
        }

        public int getKeyOffset() {
            return keyOffset;
        }

        public void setKeyOffset(int keyOffset) {
            this.keyOffset = keyOffset;
        }

        public int getKeyLen() {
            return keyLen;
        }

        public void setKeyLen(int keyLen) {
            this.keyLen = keyLen;
        }

        public int compare(Object o) {
            Key key = (Key)o;
            return BytesUtils.compare(keyBytes, keyOffset, keyLen,
                    key.getKeyBytes(), key.getKeyOffset(), key.getKeyLen());
        }

        public Object clone() {
            byte[] bytes = Arrays.copyOfRange(keyBytes, keyOffset, keyOffset + keyLen);
            return new Key(bytes, tag, timestamp);
        }

        public int hashCode() {
            if (keyBytes == null)
                return 0;

            return BytesUtils.FNVHash(keyBytes, keyOffset, keyLen);
        }

        public boolean equals(Object o) {
            return compare(o) == 0;
        }
    }

    Key getKey();

    /**
     * 返回所有数据编码后字节长度，用于预分配存储位置
     * 这里包含key的部分
     * @return
     */
    int getDataLen();

    /**
     * 写入所有字段编码之后的数据
     * 该操作会改变data的内部pos值
     * @return
     */
    void writeData(ByteBuffer data);

    /**
     * 从buffer中读取所有数据
     * 该操作会改变data内部pos值
     * @param data
     */
    void readData(ByteBuffer data);

    /**
     * 恢复对象的初始状态，实现对象复用
     */
    void clear();
}
